#coding=utf-8
#
# 版权所有 2011 沙发客团队
# 遵循Apache License 2.0协议
#    具体见 http://www.apache.org/licenses/LICENSE-2.0
#
'''
Created on 2011-3-17

@author: nava
'''
import wx, ConfigParser, codecs
import sys
import os
import time
import traceback 
import threading
from logger import Logger
from shafa import ThreadManager
from const import *
from weibopy.auth import OAuthHandler, BasicAuthHandler
from weibopy.api import API
from notification_manager import NotificationManager
import wx.lib.hyperlink as hyperlink

APP_NAME = u"沙发客, 让沙发飞一会"

exe_path = sys.executable
exe_name = os.path.basename(exe_path)
# 我们通过运行script来调试程序
if exe_name == 'python.exe':
    ICON_SHAFA = os.path.join(os.getcwd(), u'shafake.ico')
else:
    ICON_SHAFA = exe_path + ";0"


def EVT_NOTIFICATION(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_NOTIFICATION_ID, func)


class ShafakeFrame(wx.Frame):
    def __init__(self, frame):
        self._logger               = Logger()
        self._core                 = ThreadManager()
        self._parent_frame         = frame
        
        wx.Frame.__init__(self, 
            None, 
            -1, 
            APP_NAME, 
            size = (300,210),
            pos = wx.DefaultPosition, 
            style = wx.DEFAULT_FRAME_STYLE^(wx.RESIZE_BORDER |wx.MAXIMIZE_BOX))

        try:
            self._panel = wx.Panel(self, -1)
            #
            # 设置窗口左上角的图标
            #
            self.SetIcon(wx.Icon(ICON_SHAFA, wx.BITMAP_TYPE_ICO))
            
            #
            # 添加panel
            #
            self.company_panel = CompanyLoginPanel(self, -1) 
            self.company_panel.Show(True)
            
            #
            # 绑定关闭窗口事件
            # 
            self.Bind(wx.EVT_CLOSE, self.OnClose)
            EVT_NOTIFICATION(self, self.OnNotification)
        except Exception, ex:
            self._logger.error(ex)
            self._logger.error(traceback.format_exc())
            
        
    def OnStop(self):
        ''' 处理暂停事件
        @param event:
        '''
        self._core.stop_thread_event.clear()


    def OnBegin(self):
        '''  开始抢沙发
        '''
        self._btn_login.SetLabel(u"暂停")
        if self._core.StartShafa() == False:
            self._logger.error(u"启动程序失败")
            return False
        
        self._core.stop_thread_event.set()

    
    def OnClose(self, event):
        """ 处理关闭操作 """
        dialog = wx.MessageDialog(None, u'确定要退出', u"退出", wx.YES_NO |wx.ICON_INFORMATION)
        if dialog.ShowModal() == wx.ID_YES:
            self._core.StopShafa()
            self.Destroy()
            sys.exit(0)
        else:
            return

    def OnNotification(self, event):
        """主窗口线程响应后台线程发送过来的事件"""
        mess = ''
        try:
            if event.data == NOTIFICATION_UPDATE_MESS:
                mess = "更新沙发信息"
                self.HandleUpdateMess(event.key)
            elif event.data == NOTIFICATION_UPDATE_LABLE:
                mess = "更新界面按钮"
                self.HandleUpdateLable(event.key, event.key2)
            elif event.data == NOTIFICATION_UPDATE_TIME:
                mess = "更新倒计时"
                self.HandleUpdateTimer(event.key, event.key2)
            elif event.data == NOTIFICATION_RUSH_TIME:
                self.HandleRush(event.key, event.key2)
            else:
                mess = "没有此通知事件"
            
        except Exception, ex:
            self._logger.warning(ex)

    def HandleUpdateMess(self, msg):
        """修改 message label"""
        self._core.main_panel.wibo_text.SetLabel(msg)

    def HandleUpdateLable(self, comment_count, wibo_count):
        """修改 count label"""
        self._core.main_panel.comment_count_text.SetLabel(str(comment_count))
        self._core.main_panel.wibo_count_text.SetLabel(str(wibo_count))
        
    def HandleUpdateTimer(self, msg, time):
        """计数器"""
        self._core.main_panel.msg = msg
        self._core.main_panel.time = time
        self._core.main_panel.timer.Start(1000)
    
    def HandleRush(self, message, rush_time):
        """ 处理间隔时间 """
        self._core.main_panel.UpdateRushTimer(message, rush_time)
    
class CompanyLoginPanel(wx.Panel):
    ''' 登录panel
    '''
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent._panel, id, pos = (5,5), size= (300, 210))

        self._parent = parent
        
        self._core   = ThreadManager()
        image = wx.Image(u"sina.png", wx.BITMAP_TYPE_ANY,-1)
        wx.StaticBitmap(self, -1, wx.BitmapFromImage(image), 
                                  size= (image.GetWidth(), image.GetHeight()), 
                                  pos=(0,0))
        
        #
        # 导入配置文件
        #
        
        full_path = os.path.join(self.StrToGbk(os.getcwd()), u'setting.ini')
        name = self.__GetConfigValue(u'\u8d26\u6237\u8bbe\u7f6e', "user_name", full_path)
        
        wx.StaticText(self, -1, u"账号:", pos = (10,80), size = (40,30))
        if name == None:
            self.userName_text = wx.TextCtrl(self, -1, u"用户账号", pos = (50,75), size = (210,25))
        else:
            self.userName_text = wx.TextCtrl(self, -1, name, pos = (50,75), size = (210,25))
         
        wx.StaticText(self, -1, u"密 码:", pos = (10,107), size = (40,20))
        self.password_text = wx.TextCtrl(self, -1, "", pos = (50,105), size = (210,25), style=(wx.TE_PASSWORD))
         
        self.btn_login = wx.Button(self, -1, u"登录", pos = (20, 135), size = (80,30))
        self.btn_exit  = wx.Button(self, -1, u"退出", pos = (150, 135), size = (80,30))
        #self.btn_login.SetForegroundColour((0,0,255))
        #self.btn_login.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False))

        #
        # 添加验证失败时的信息
        #
        self._validateInfo_text = wx.StaticText(self, -1, "", pos = (20,60), size = (80,-1))
        self._validateInfo_text.SetForegroundColour((255,0,0))
        self._validateInfo_text.Hide()
        
        #
        # 绑定事件
        #
        self.is_username_text_lose_focus = False
        
        #
        # 绑定按钮事件
        #
        self.Bind(wx.EVT_BUTTON, self.OnBtnLogin, self.btn_login)
        self.Bind(wx.EVT_BUTTON, self.OnClose, self.btn_exit)

    def StrToGbk(self, value):
        """ 支持中文，转成gb2312 """
        try:
            if isinstance(value, str):
                value    = unicode(value, "utf-8", errors="ignore")
        except:
            pass
        value    = value.encode('gb2312', "ignore")
        value    = value.decode('gb2312', "ignore")
        return value

    def OnBtnLogin(self,event):
        ''' 处理按钮事件
        @param event:
        '''
        self.OnLogin()
        
    def OnClose(self, event):
        """ 处理退出按钮事件 """
        self._parent.OnClose(event)
        
    def OnLogin(self):
        """ 处理登录逻辑操作 """
        # 
        # 启动core线程
        #
        if self.OnValidateText() == False:
            return False
        if self.__VerifyUser() == False:
            return False
        self._core.user_name = self.userName_text.GetValue()
        self._core.password  = self.password_text.GetValue()
        
        self._core.main_panel = ShowPanel(self._parent, -1)
        self._core.main_panel.Show()
        
        #登录panel隐藏
        self.Hide()
        # 保存用户名 到配置文件
        full_path = os.path.join(self.StrToGbk(os.getcwd()), u'setting.ini')
        self.__UpdateConfig(u'\u8d26\u6237\u8bbe\u7f6e', "user_name", full_path, self._core.user_name)
        #
        # 启动
        #
        self._core.StartShafa()
    
    def __UpdateConfig(self, section, option, full_path, value):
        """  更新对应配置信息  """
        if full_path == None:
            return False
        if os.path.exists(full_path) == False:
            return False
        try:
            config = ConfigParser.ConfigParser()
            config.readfp(codecs.open(full_path, "r", "utf-8-sig"))
            if config.has_section(section) == False:
                config.add_section(section)

            config.set(section, option, value)
        except Exception, ex:
            print traceback.format_exc()
            return False

        try:
            f = open(full_path, "w")
            config.write(f)
            f.close()
        except Exception, ex:
            self._logger.error(ex)
            self._logger.error(traceback.format_exc())
            return False
        return True
    
    def __GetConfigValue(self, section, option, full_path):
        """从配置文件获取名称"""
        if os.path.exists(full_path) == False:
            return None
        try:
            config = ConfigParser.ConfigParser()
            config.readfp(codecs.open(full_path, "r", "utf-8-sig"))
            return config.get(section, option)
        except Exception, ex:
            return None
    
    def __VerifyUser(self):
        ''' 验证该用户是否存在
        '''
        try:
            self._auth = BasicAuthHandler(self.userName_text.GetValue(), self.password_text.GetValue())
            self._api = API(self._auth,
                            host    = WEIBO_HOST, 
                            source  = APP_KEY)
            #
            # 获取用户自己的信息
            #
            user = self._api.verify_credentials()
            if user:
                self._displayname = user.screen_name
            else:
                self._validateInfo_text.SetLabel(u"用户不存在或者密码错误")
                self._validateInfo_text.Show()
                return False
        except Exception, ex:
            print traceback.format_exc()
            self._validateInfo_text.SetLabel(u"用户不存在或者密码错误")
            self._validateInfo_text.Show()
            return False
        return True
    
    def OnValidateText(self):
        msg = u""
        
        if self.userName_text.GetValue() == "":
            msg = u"请输入您的用户名"
        elif self.password_text.GetValue() == "":
            msg = u"请输入您的密码"
        
        if msg == u"":
            return True
        
        self._validateInfo_text.SetLabel(msg)
        self._validateInfo_text.Show()
        return False
    
class ShowPanel(wx.Panel):
    ''' 显示沙发信息
    '''
    def __init__(self, parent, id):
        wx.Panel.__init__(self, parent._panel, id, pos = (5,5), size= (430,110))
        
        parent.SetSize(size=(430, 120))

        self.msg  = None
        self.time = None
        #创建一个文本控件  
        self.wibo_text = wx.StaticText(self, -1, "", pos = (10,5), size = (310,40), style=wx.STATIC_BORDER | wx.ST_NO_AUTORESIZE)
        
        wx.StaticText(self, -1, u"沙发", pos = (10,55), size = (30,30))
        self.comment_count_text = wx.StaticText(self, -1, "0", pos = (40,55), size = (40,20), style=wx.STATIC_BORDER | wx.ST_NO_AUTORESIZE | wx.ALIGN_CENTER)
        wx.StaticText(self, -1, u"转发", pos = (90,55), size = (30,30))
        self.wibo_count_text = wx.StaticText(self, -1, "0", pos = (120,55), size = (40,20), style=wx.STATIC_BORDER | wx.ST_NO_AUTORESIZE | wx.ALIGN_CENTER)
        
        self.timer = wx.Timer(self, -1)
        self.Bind(wx.EVT_TIMER, self.StartTimer, self.timer)
        
        hyperlink.HyperLinkCtrl(self, -1, u"关于我们", URL = "http://code.google.com/p/shafake/", pos = (220,55), size = (100,-1))
        
        self.btn_rush = wx.Button(self, -1, u"抢", pos = (330, 5), size = (80,55))
        self.btn_rush.SetForegroundColour((0,0,255))
        self.btn_rush.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False))
        self.btn_rush.Enable(False)

        #
        # 绑定按钮事件
        #
        self.Bind(wx.EVT_BUTTON, self.OnRush, self.btn_rush)

        self._rush_timer    = None
        self._core          = ThreadManager()
        self.rush_time      = 0
    
    def UpdateRushTimer(self, message, rush_time):
        """ 更新抢沙发timer """
        if self._rush_timer == None:
            self._rush_timer = wx.Timer(self, -1)
            self.Bind(wx.EVT_TIMER, self.RushTimer, self._rush_timer)

        #
        # 更新变量
        #
        self.rush_time      = rush_time
        self._rush_timer.Start(1000)
        self.wibo_text.SetLabel(message)
        if rush_time > 0:
            self.btn_rush.Enable(True)

    def RushTimer(self, event):
        if self.rush_time <= 0 and self._rush_timer:
            self.btn_rush.SetLabel(u"抢")
            self.btn_rush.Enable(False)
            self._rush_timer.Stop()
            self._rush_timer = None
            return

        self.btn_rush.SetLabel(u"抢(%d)" % self.rush_time)
        self.rush_time -= 1
        
    def StartTimer(self, event):
        ''' 倒计时
        @param event:
        '''
        self.time = self.time - 1
        
        if (self.time <= 0):
            self.wibo_text.SetLabel("")
            self.timer.Stop()
            return
        
        minute = self.time/60
        if minute < 10: minute = "0" + str(minute)
        second = self.time%60
        t = str(minute) + ":" + str(second)
        
        self.wibo_text.SetLabel(self.msg + u"\n倒计时: " + t)
        
    def OnRush(self, event):
        ''' 处理按钮事件
        @param event:
        '''
        self._core.YouMustRush()
        self.rush_time = 0
        self.btn_rush.Enable(False)
        #import win32api, win32con
        #win32api.ShellExecute(0, None, 'notepad', CONFIG_SETTING_FILE, '-new', win32con.SW_NORMAL)

class MyApp(wx.App):
    def OnInit(self):
        
        #
        # 修改默认utf-8编码
        #
        import sys  
        reload(sys) 
        sys.setdefaultencoding('utf-8')
        
        shafake_frame = ShafakeFrame(self)
        shafake_frame.Centre()
        shafake_frame.Show(True)
        self.SetTopWindow(shafake_frame)
        NotificationManager().SetWindowsFram(shafake_frame)
        
        return True

if __name__ == '__main__':
    app = MyApp(0)
    app.MainLoop()